import 'package:json_annotation/json_annotation.dart';

part 'file_metadata.g.dart';

@JsonSerializable()
class FileMetadata {
  final int? id;
  final String md5;
  final String fileName;
  final int fileSize;
  final String? mimeType;
  final String? cloudId;
  final DateTime createdTime;
  final DateTime updatedTime;

  FileMetadata({
    this.id,
    required this.md5,
    required this.fileName,
    required this.fileSize,
    this.mimeType,
    this.cloudId,
    required this.createdTime,
    required this.updatedTime,
  });

  factory FileMetadata.fromJson(Map<String, dynamic> json) =>
      _$FileMetadataFromJson(json);

  Map<String, dynamic> toJson() => _$FileMetadataToJson(this);

  factory FileMetadata.fromMap(Map<String, dynamic> map) {
    return FileMetadata(
      id: map['id']?.toInt(),
      md5: map['md5'] ?? '',
      fileName: map['file_name'] ?? '',
      fileSize: map['file_size']?.toInt() ?? 0,
      mimeType: map['mime_type'],
      cloudId: map['cloud_id'],
      createdTime: DateTime.parse(map['created_time'] ?? DateTime.now().toIso8601String()),
      updatedTime: DateTime.parse(map['updated_time'] ?? DateTime.now().toIso8601String()),
    );
  }

  Map<String, dynamic> toMap() {
    return {
      'id': id,
      'md5': md5,
      'file_name': fileName,
      'file_size': fileSize,
      'mime_type': mimeType,
      'cloud_id': cloudId,
      'created_time': createdTime.toIso8601String(),
      'updated_time': updatedTime.toIso8601String(),
    };
  }

  FileMetadata copyWith({
    int? id,
    String? md5,
    String? fileName,
    int? fileSize,
    String? mimeType,
    String? cloudId,
    DateTime? createdTime,
    DateTime? updatedTime,
  }) {
    return FileMetadata(
      id: id ?? this.id,
      md5: md5 ?? this.md5,
      fileName: fileName ?? this.fileName,
      fileSize: fileSize ?? this.fileSize,
      mimeType: mimeType ?? this.mimeType,
      cloudId: cloudId ?? this.cloudId,
      createdTime: createdTime ?? this.createdTime,
      updatedTime: updatedTime ?? this.updatedTime,
    );
  }

  @override
  String toString() {
    return 'FileMetadata(id: $id, md5: $md5, fileName: $fileName, fileSize: $fileSize, mimeType: $mimeType, cloudId: $cloudId, createdTime: $createdTime, updatedTime: $updatedTime)';
  }

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) return true;
    return other is FileMetadata &&
        other.id == id &&
        other.md5 == md5 &&
        other.fileName == fileName &&
        other.fileSize == fileSize &&
        other.mimeType == mimeType &&
        other.cloudId == cloudId &&
        other.createdTime == createdTime &&
        other.updatedTime == updatedTime;
  }

  @override
  int get hashCode {
    return id.hashCode ^
        md5.hashCode ^
        fileName.hashCode ^
        fileSize.hashCode ^
        mimeType.hashCode ^
        cloudId.hashCode ^
        createdTime.hashCode ^
        updatedTime.hashCode;
  }
}